package com.pnnd.stream;

import java.nio.ByteBuffer;
import java.util.Collection;

public interface Buffer {

    /**
     * 是否为缓存，cache用于统一管理一大批memorySegment，
     * cache中memorySegment在cache没有关闭时不会被close
     * 只有全部segment在cache中时才为true
     * @return bool
     */
    boolean isCache();

    /**
     * 获取当前buffer 总的offset，基础offset为0，
     * 当写入数据后 offset = 写入数据总量
     * @return int
     */
    int offset();

    /**
     * 当前文件的权限
     * 类似于 wreb 的描述
     * @see BufferTag
     * @return long
     */
    BufferTag tag();

    /**
     * buffer 类型
     */
    BufferType type();

    /**
     * Tags this buffer to represent an event.
     */
    void tagAsEvent();

    /**
     * 当前buffer的所有内存段
     * @return collection
     */
    Collection<MemorySegment> getMemorySegment();

    /**
     * 当前正在使用的MemorySegment
     * @return MemorySegment
     */
    MemorySegment currentMemorySegment();

    /**
     * This method will be removed in the future. For writing use
     *
     * @return the offset where this (potential slice) {@link Buffer}'s data start in the underlying memory segment.
     */
    int getMemorySegmentOffset();

    /**
     * Releases this buffer once, i.e. reduces the reference count and recycles the buffer if the
     * reference count reaches <tt>0</tt>.
     *
     * @see #retainBuffer()
     */
    void recycleBuffer();

    /**
     * Returns whether this buffer has been recycled or not.
     *
     * @return <tt>true</tt> if already recycled, <tt>false</tt> otherwise
     */
    boolean isRecycled();

    /**
     * Retains this buffer for further use, increasing the reference counter by <tt>1</tt>.
     *
     * @return <tt>this</tt> instance (for chained calls)
     *
     * @see #recycleBuffer()
     */
    Buffer retainBuffer();

    /**
     * Returns a read-only slice of this buffer's readable bytes, i.e. between
     * {@link #getReaderIndex()} and {@link #getSize()}.
     *
     * <p>Reader and writer indices as well as markers are not shared. Reference counters are
     * shared but the slice is not {@link #retainBuffer() retained} automatically.
     *
     * @return a read-only sliced buffer
     */
    Buffer readOnlySlice();

    /**
     * Returns a read-only slice of this buffer.
     *
     * <p>Reader and writer indices as well as markers are not shared. Reference counters are
     * shared but the slice is not {@link #retainBuffer() retained} automatically.
     *
     * @param index the index to start from
     * @param length the length of the slice
     *
     * @return a read-only sliced buffer
     */
    Buffer readOnlySlice(int index, int length);

    /**
     * Returns the maximum size of the buffer, i.e. the capacity of the underlying {@link MemorySegment}.
     *
     * @return size of the buffer
     */
    int getMaxCapacity();

    /**
     * Returns the <tt>reader index</tt> of this buffer.
     *
     * <p>This is where readable (unconsumed) bytes start in the backing memory segment.
     *
     * @return reader index (from 0 (inclusive) to the size of the backing {@link MemorySegment}
     * (inclusive))
     */
    int getReaderIndex();

    /**
     * Sets the <tt>reader index</tt> of this buffer.
     *
     * @throws IndexOutOfBoundsException
     * 		if the index is less than <tt>0</tt> or greater than {@link #getSize()}
     */
    void setReaderIndex(int readerIndex) throws IndexOutOfBoundsException;

    /**
     * Returns the size of the written data, i.e. the <tt>writer index</tt>, of this buffer.
     *
     * <p>This is where writable bytes start in the backing memory segment.
     *
     * @return writer index (from 0 (inclusive) to the size of the backing {@link MemorySegment}
     * (inclusive))
     */
    int getSize();

    /**
     * Sets the size of the written data, i.e. the <tt>writer index</tt>, of this buffer.
     *
     * @throws IndexOutOfBoundsException
     * 		if the index is less than {@link #getReaderIndex()} or greater than {@link #getMaxCapacity()}
     */
    void setSize(int writerIndex);

    /**
     * Returns the number of readable bytes (same as <tt>{@link #getSize()} -
     * {@link #getReaderIndex()}</tt>).
     */
    int readableBytes();

    /**
     * Gets a new {@link ByteBuffer} instance wrapping this buffer's readable bytes, i.e. between
     * {@link #getReaderIndex()} and {@link #getSize()}.
     *
     * <p>Please note that neither index is updated by the returned buffer.
     *
     * @return byte buffer sharing the contents of the underlying memory segment
     */
    ByteBuffer getNioBufferReadable();

    /**
     * Gets a new {@link ByteBuffer} instance wrapping this buffer's bytes.
     *
     * <p>Please note that neither <tt>read</tt> nor <tt>write</tt> index are updated by the
     * returned buffer.
     *
     * @return byte buffer sharing the contents of the underlying memory segment
     *
     * @throws IndexOutOfBoundsException
     * 		if the indexes are not without the buffer's bounds
     * @see #getNioBufferReadable()
     */
    ByteBuffer getNioBuffer(int index, int length) throws IndexOutOfBoundsException;

    /**
     * 延伸当前buffer
     * @see BufferTag
     * @param segment 要追加的内存段
     */
    void extend(MemorySegment segment);

    /**
     * 将buffer中数据dump到文件中
     * @param path 文件路径
     */
    void dump(String path);
}
